package com.itheima.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.pinda.exception.BizException;
import com.itheima.wms.common.constants.CodeConstant;
import com.itheima.wms.common.enums.*;
import com.itheima.wms.common.service.CrudServiceImpl;
import com.itheima.wms.dao.*;
import com.itheima.wms.entity.*;
import com.itheima.wms.factory.CodeWorker;
import com.itheima.wms.service.*;
import com.itheima.wms.vo.BatchVO;
import com.itheima.wms.vo.CheckTaskDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 业务实现类
 * 盘点任务
 * </p>
 */
@Slf4j
@Service
public class CheckTaskServiceImpl extends CrudServiceImpl<CheckTaskMapper, CheckTaskEntity> implements CheckTaskService {

    @Autowired
    private CheckMapper checkMapper;
    @Autowired
    private CheckListMapper checkListMapper;
    @Autowired
    private CheckListService checkListService;
    @Autowired
    private StockMapper stockMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private IncreaseDecreaseService increaseDecreaseService;
    @Autowired
    private StockService stockService;
    @Autowired
    private StockRecordMapper stockRecordMapper;
    @Autowired
    private StatusRecordService statusRecordService;

    @Override
    @Transactional
    public BatchVO complete(List<Long> ids) {
        BatchVO.BatchVOBuilder batchVOBuilder = BatchVO.builder();

        ids.forEach(id -> {
            CheckTaskEntity checkTaskEntity = this.getById(id);
            if (null == checkTaskEntity) {
                log.info("id:{} 未找到", id);
                return;
            }

            // 校验清单是否有未填写的
            LambdaQueryWrapper<CheckListEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CheckListEntity::getMasterId, checkTaskEntity.getMasterId());
            List<CheckListEntity> checkListEntities = checkListMapper.selectList(wrapper);
            checkListEntities = checkListEntities.stream().filter(item -> null != item.getCheckNum()).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(checkListEntities)) {
                log.info("id:{} 清单未填写完成", id);
                batchVOBuilder.error(checkTaskEntity.getCode() + "未完成盘点单录入");
                return;
            }

            if (CheckTaskStatus.CHECK.getCode() != checkTaskEntity.getStatus()) {
                log.info("id:{} 状态不符 status:{}", id, checkTaskEntity.getStatus());
                batchVOBuilder.error(checkTaskEntity.getCode() + "状态不合法");
                return;
            }

            // 修改盘点任务 为 盘点已完成
            checkTaskEntity.setStatus(CheckTaskStatus.CHECK_COMPLETED.getCode());
            this.updateById(checkTaskEntity);
            statusRecordService.saveStatus(checkTaskEntity);

            CheckEntity checkEntity = checkMapper.selectById(checkTaskEntity.getMasterId());
            // 修改盘点单状态为 一盘完成
            if (1 == checkTaskEntity.getCheckNum()) {
                // 一盘
                checkEntity.setStatus(CheckStatus.CHECK_COMPLETED.getCode());
                // 只保留一盘清单
                checkListEntities = checkListEntities.stream().filter(item -> item.getStatus() == 1).collect(Collectors.toList());
            } else {
                // 复盘
                checkEntity.setStatus(CheckStatus.RECHECK_COMPLETED.getCode());
                // 只保留复盘清单
                checkListEntities = checkListEntities.stream().filter(item -> item.getStatus() == 2).collect(Collectors.toList());
            }
            checkMapper.updateById(checkEntity);
            statusRecordService.saveStatus(checkEntity);

            // 解冻
            unfreezeStock(checkListEntities);

            batchVOBuilder.result(checkEntity.getCode());
        });

        return batchVOBuilder.build();
    }

    /**
     * 解冻库存
     *
     * @param checkListEntities
     */
    private void unfreezeStock(List<CheckListEntity> checkListEntities) {
        checkListEntities.forEach(checkListEntity -> {
            Long stockId = checkListEntity.getStockId();
            Integer stockNum = checkListEntity.getStockNum();
            StockEntity stockEntity = stockService.getById(stockId);
            log.info("盘点任务解冻 checkListEntity:{} stockEntity:{}", checkListEntity, stockEntity);
            Integer original = stockEntity.getTotal();
            Integer originalFree = stockEntity.getFree();
            stockService.unfreeze(stockId, stockNum);

            StockRecordEntity stockRecordEntity = new StockRecordEntity();
            stockRecordEntity.setSourceId(checkListEntity.getId());
            stockRecordEntity.setLocationId(stockEntity.getLocationId());
            stockRecordEntity.setType(StockRecordType.PD.getCode());// 类型出库
            stockRecordEntity.setOriginal(original);
            stockRecordEntity.setOriginalFree(originalFree);
            stockRecordEntity.setWay(StockRecordWay.UNFREEZE.getCode());
            stockRecordEntity.setAlteration(stockNum);
            stockRecordEntity.setResult(original);
            stockRecordEntity.setResultFree(originalFree + stockNum);
            stockRecordMapper.insert(stockRecordEntity);
        });
    }

    @Override
    public BatchVO task(List<Long> ids) {
        BatchVO.BatchVOBuilder batchVOBuilder = BatchVO.builder();
        ids.forEach(id -> {
            try {
                String code = task(id);
                batchVOBuilder.result(code);
            } catch (BizException e) {
                log.warn("id:{} 复盘任务生成失败", id, e);
                batchVOBuilder.error(e.getMessage());
            } catch (Exception e) {
                log.error("id:{} 复盘任务生成异常", id, e);
                batchVOBuilder.error("位置异常");
            }

        });
        return batchVOBuilder.build();
    }

    @Override
    @Transactional
    public String task(Long id) {
        CheckTaskEntity checkTaskEntity = getById(id);

        if (null == checkTaskEntity) {
            log.info("id:{} 未找到", id);
        }

        if (checkTaskEntity.getCheckNum() == CheckTaskCheckNum.RECHECK.getCode()) {
            log.info("id:{} 复盘任务无法生成复盘", id);
            throw new BizException(checkTaskEntity.getCode() + "复盘任务无法生成复盘");
        }

        if (checkTaskEntity.getStatus() == CheckTaskStatus.RECHECK.getCode()) {
            log.info("id:{} 已生成复盘任务", id);
            throw new BizException(checkTaskEntity.getCode() + "已生成复盘任务");
        }

        if (checkTaskEntity.getStatus() != CheckTaskStatus.CHECK_COMPLETED.getCode()) {
            log.info("id:{} 一盘未完成", id);
            throw new BizException(checkTaskEntity.getCode() + "未完成一盘");
        }

        try {
            checkTaskEntity.setStatus(CheckTaskStatus.RECHECK.getCode());
            this.updateById(checkTaskEntity);
            statusRecordService.saveStatus(checkTaskEntity);

            CheckEntity checkEntity = checkMapper.selectById(checkTaskEntity.getMasterId());
            checkEntity.setStatus(CheckStatus.RECHECK.getCode());
            checkMapper.updateById(checkEntity);
            statusRecordService.saveStatus(checkEntity);

            // 复制原有盘点任务
            checkTaskEntity.setId(null);
            checkTaskEntity.setCode(CodeWorker.nextCode(CodeConstant.CHECKTASK));
            checkTaskEntity.setCheckNum(CheckListStatus.RECHECK.getCode()); // 设置盘点次数为 2
            checkTaskEntity.setStatus(CheckTaskStatus.NEW.getCode());
            checkTaskEntity.setCheckTotal(null);
            checkTaskEntity.setPersonName(null);
            checkTaskEntity.setDifferenceNum(null);
            checkTaskEntity.setCreateTime(LocalDateTime.now());
            checkTaskEntity.setUpdateTime(LocalDateTime.now());
            save(checkTaskEntity);
            statusRecordService.saveStatus(checkTaskEntity);

            // 复制盘点单清单
            LambdaQueryWrapper<CheckListEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CheckListEntity::getMasterId, checkTaskEntity.getMasterId());
            List<CheckListEntity> checkListEntities = checkListService.list(wrapper);
            checkListEntities.forEach(item -> {
                item.setId(null);
                item.setStatus(CheckListStatus.RECHECK.getCode());
                item.setDifferenceNum(null);
                item.setCheckNum(null);
            });
            checkListService.saveBatch(checkListEntities);
        } catch (BizException e) {
            throw new BizException(checkTaskEntity.getCode() + e.getMessage());
        }
        return checkTaskEntity.getCode();
    }

    @Override
    @Transactional
    public BatchVO increaseDecrease(List<Long> ids) {
        BatchVO.BatchVOBuilder batchVOBuilder = BatchVO.builder();

        ids.forEach(id -> {
            CheckTaskEntity checkTaskEntity = getById(id);

            if (null == checkTaskEntity) {
                log.info("id:{} 未找到", id);
                return;
            }

            if (checkTaskEntity.getDifferenceNum() == null || checkTaskEntity.getDifferenceNum() == 0) {
                batchVOBuilder.error(checkTaskEntity.getCode() + "没有损益");
                return;
            }

            // 差异数大于0 查询明细 生成损益单
            LambdaQueryWrapper<CheckListEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CheckListEntity::getMasterId, checkTaskEntity.getMasterId());
            queryWrapper.eq(CheckListEntity::getStatus, checkTaskEntity.getCheckNum());
            queryWrapper.ne(CheckListEntity::getDifferenceNum, 0);
            List<CheckListEntity> checkListEntities = checkListService.list(queryWrapper);
            List<IncreaseDecreaseEntity> increaseDecreaseEntityList = new ArrayList<>();
            for (CheckListEntity checkListEntity : checkListEntities) {
                LambdaQueryWrapper<IncreaseDecreaseEntity> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(IncreaseDecreaseEntity::getTaskId, checkListEntity.getId());
                int cou = increaseDecreaseService.count(wrapper);
                if (cou > 0) {
                    batchVOBuilder.error(checkTaskEntity.getCode() + "已存在损益单");
                    continue;
                }
                StockEntity stockEntity = stockMapper.selectById(checkListEntity.getStockId());
                // 查询货品信息
                GoodsEntity goods = goodsMapper.selectById(stockEntity.getGoodsId());

                IncreaseDecreaseEntity increaseDecreaseEntity = new IncreaseDecreaseEntity();
                increaseDecreaseEntity.setCode(CodeWorker.nextCode(CodeConstant.INCREASEDECREASE));
                increaseDecreaseEntity.setStockId(stockEntity.getId());
                increaseDecreaseEntity.setIdNum(checkListEntity.getDifferenceNum());// 差异数量
                if (null != goods.getPrice()) {
                    increaseDecreaseEntity.setIdMoney(goods.getPrice().multiply(new BigDecimal(increaseDecreaseEntity.getIdNum())));
                }
                increaseDecreaseEntity.setIdSource(IncreaseDecreaseIdSource.PD.getCode());
                increaseDecreaseEntity.setTaskId(checkListEntity.getId());
                increaseDecreaseEntity.setTaskCode(checkTaskEntity.getCode());
                increaseDecreaseEntity.setStatus(IncreaseDecreaseStatus.NEW.getCode());
                increaseDecreaseEntityList.add(increaseDecreaseEntity);
            }
            if (!CollectionUtils.isEmpty(increaseDecreaseEntityList)) {
                increaseDecreaseService.saveBatch(increaseDecreaseEntityList);
                checkTaskEntity.setStatus(CheckTaskStatus.INCREASE_DECREASE.getCode());
                this.updateById(checkTaskEntity);
                statusRecordService.saveStatus(checkTaskEntity);
                batchVOBuilder.results(increaseDecreaseEntityList.stream().map(item -> item.getCode()).collect(Collectors.toList()));
            }
        });
        return batchVOBuilder.build();
    }

    @Override
    public IPage<CheckTaskDetailVO> pageDetail(Page<CheckTaskDetailVO> page, Map data) {
        IPage<CheckTaskDetailVO> iPage = this.baseMapper.selectCheckTaskDetail(page, data);
        return iPage;
    }
}

